package com.feature50.clarity.table;

import com.feature50.util.ArrayUtils;
import com.feature50.util.ReflectionUtils;

import java.util.List;
import java.util.ArrayList;

public class ValuePath {
    private String[] paths;
    private int[] indices;
    private String field;
    private String description;

    public ValuePath(String[] paths, int[] indices, String field) {
        this.paths = paths;
        this.indices = indices;
        this.field = field;
    }

    public ValuePath(String description, String[] paths, int[] indices, String field) {
        this.description = description;
        this.paths = paths;
        this.indices = indices;
        this.field = field;
    }

    public String[] getPaths() {
        return paths;
    }

    public int[] getIndices() {
        return indices;
    }

    public String getField() {
        return field;
    }

    public synchronized String getDescription() {
        if (description == null) {
            StringBuffer sb = new StringBuffer();

            for (int i = 0; i < paths.length; i++) {
                String path = paths[i];
                sb.append(path);
                sb.append("[");
                sb.append(indices[i]);
                sb.append("](");
            }

            sb.append(field);

            for (int i = 0; i < paths.length - 1; i++) {
                sb.append(")");
            }

            description = sb.toString();
        }

        return description;
    }

    public Object getFieldInstance(Object object) throws Exception {
        Object fieldInstance = object;  // the instance used to retrieve the value

        if (!ArrayUtils.isNullOrEmpty(getPaths())) {
            for (int i = 0; i < getPaths().length; i++) {
                String p = getPaths()[i];
                Object indexedProperty = ReflectionUtils.invokeGetter(fieldInstance, p);
                fieldInstance = ArrayUtils.getIndex(indexedProperty, getIndices()[i]);
            }
        }

        return fieldInstance;
    }

    public static ValuePath[] getValuePaths(Object instance, String pathDescription) {
        if ((pathDescription.indexOf("[") != -1) ||
                (pathDescription.indexOf("]") != -1) ||
                (pathDescription.indexOf("(") != -1) ||
                (pathDescription.indexOf(")") != -1)) {
            throw new IllegalArgumentException("Expansion of indexed properties not yet supported");
        }

        return new ValuePath[] { new ValuePath(new String[0], new int[0], pathDescription) };
    }
}
